package pl.edu.agh.ki.neuralnetwork.builder;

import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import pl.edu.agh.ki.neuralnetwork.exceptions.NeuronAlreadyConnectedException;
import pl.edu.agh.ki.neuralnetwork.exceptions.NotEnoughLayersException;
import pl.edu.agh.ki.neuralnetwork.exceptions.NotEnoughNeuronsException;
import pl.edu.agh.ki.neuralnetwork.layer.Layer;
import pl.edu.agh.ki.neuralnetwork.layer.SimpleLayer;
import pl.edu.agh.ki.neuralnetwork.network.NeuralNetwork;
import pl.edu.agh.ki.neuralnetwork.network.NeuralNetworkImpl;
import pl.edu.agh.ki.neuralnetwork.neurons.InnerNeuron;
import pl.edu.agh.ki.neuralnetwork.neurons.InputNeuron;
import pl.edu.agh.ki.neuralnetwork.neurons.InputNeuronImpl;
import pl.edu.agh.ki.neuralnetwork.neurons.SigmoidalNeuron;

public class ManualNetworkBuilder implements NeuralNetworkBuilder {

    public NeuralNetwork build() {
        NeuralNetwork network = null;
        try {
        	Layer<InputNeuron> inputNeurons = new SimpleLayer<InputNeuron>();

            //=== tu definiuj liczbę wejść
            int liczbaWejsc = 2;
            //===

            for (int i = 0; i < liczbaWejsc; i++) {
                inputNeurons.add(new InputNeuronImpl());
            }


            //=== tu zdefiniuj wartości wejść
            Double input[] = { 0.9, 0.9 };

            for(int i=0; i<liczbaWejsc; i++)
                inputNeurons.get(i).setInput(input[i]);
            

            List<Layer<InnerNeuron>> innerLayers = new LinkedList<Layer<InnerNeuron>>();
            // warstwa 1
            Layer<InnerNeuron> layer1 = new SimpleLayer<InnerNeuron>();

                
                // neuron z liniową funkcją aktywacji
                InnerNeuron neuron11 = new SigmoidalNeuron();
                InnerNeuron neuron12 = new SigmoidalNeuron();
                neuron11.setBias( -3.328862);
                neuron12.setBias( 3.037391);
                // połączenia z wejściami
                neuron11.addInput(inputNeurons.get(0), 7.273697); // argument to waga połączenia
                neuron11.addInput(inputNeurons.get(1),  7.306096);
                neuron12.addInput(inputNeurons.get(0), -5.913371);
                neuron12.addInput(inputNeurons.get(1), 5.665226);

                layer1.add(neuron11);
                layer1.add(neuron12);

                innerLayers.add(layer1);
            // ~

            // warstwa 2
                SimpleLayer<InnerNeuron> layer2 = new SimpleLayer<InnerNeuron>();
                InnerNeuron neuron21 = new SigmoidalNeuron();
                neuron21.setBias(-4.530193);
                neuron21.addInput(neuron11, -9.61277 ); // argument to waga połączenia
                neuron21.addInput(neuron12, 10.10151 );
                layer2.add(neuron21);
                innerLayers.add(layer2);
               

            try {
                network = new NeuralNetworkImpl(inputNeurons, innerLayers);
            } catch (NotEnoughLayersException ex) {
                Logger.getLogger(SimpleLinearNetworkBuilder.class.getName()).log(Level.SEVERE, null, ex);
            } catch (NotEnoughNeuronsException ex) {
                Logger.getLogger(SimpleLinearNetworkBuilder.class.getName()).log(Level.SEVERE, null, ex);
            }
        } catch (NeuronAlreadyConnectedException ex) {
            Logger.getLogger(ManualNetworkBuilder.class.getName()).log(Level.SEVERE, null, ex);
        }
        return network;
    }
}
